﻿namespace SharePointCSVImporter.RuleEditors
{
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Windows;

    using Microsoft.SharePoint.Client;

    public class ExternalLookupVM : INotifyPropertyChanged
    {
        #region Fields

        private List<string> availableColumns;
        private bool blankIfNull;
        private string csvColumn1;
        private string csvColumn2;
        private string csvColumn3;
        private string fieldName1;
        private string fieldName2;
        private string fieldName3;
        private string fieldRetreivalStatus = "Get Fields";
        private string listName;
        private PropertyChangedEventHandler propertychanged;
        private List<Field> sourceListFields;
        private string targetFieldName;
        private bool useFirstIfMulti;
        private string webUrl;

        #endregion Fields

        #region Constructors

        public ExternalLookupVM()
        {
        }

        public ExternalLookupVM(CSVParser.FieldTransformation transform)
        {
            ReadTransformValues(transform);
        }

        #endregion Constructors

        #region Events

        event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
        {
            add { this.propertychanged += value; }
            remove { this.propertychanged -= value; }
        }

        #endregion Events

        #region Properties

        public List<string> AvailableColumns
        {
            get { return availableColumns; }
            set { availableColumns = value; OnPropertyChanged("AvailableColumns"); }
        }

        public bool BlankIfNull
        {
            get { return blankIfNull; }
            set { blankIfNull = value; OnPropertyChanged("BlankIfNull"); }
        }

        public string CsvColumn1
        {
            get { return csvColumn1; }
            set { csvColumn1 = value; OnPropertyChanged("CsvColumn1"); }
        }

        public string CsvColumn2
        {
            get { return csvColumn2; }
            set { csvColumn2 = value; OnPropertyChanged("CsvColumn2"); }
        }

        public string CsvColumn3
        {
            get { return csvColumn3; }
            set { csvColumn3 = value; OnPropertyChanged("CsvColumn3"); }
        }

        public string FieldName1
        {
            get { return fieldName1; }
            set { fieldName1 = value; OnPropertyChanged("FieldName1"); }
        }

        public string FieldName2
        {
            get { return fieldName2; }
            set { fieldName2 = value; OnPropertyChanged("FieldName2"); }
        }

        public string FieldName3
        {
            get { return fieldName3; }
            set { fieldName3 = value; OnPropertyChanged("FieldName3"); }
        }

        public string FieldRetreivalStatus
        {
            get { return fieldRetreivalStatus; }
            set { fieldRetreivalStatus = value; OnPropertyChanged("FieldRetreivalStatus"); }
        }

        public string ListName
        {
            get
            {
                if (string.IsNullOrEmpty(listName))
                {
                    listName = ConfigManager.TryGetDefaultExternalListName();
                }
                return listName;
            }
            set
            {
                listName = value;
                ConfigManager.SaveDefaultExternalListName(listName);
                OnPropertyChanged("ListName");
            }
        }

        public List<Field> SourceListFields
        {
            get { return sourceListFields; }
            set { sourceListFields = value; OnPropertyChanged("SourceListFields"); }
        }

        public string TargetFieldName
        {
            get { return targetFieldName; }
            set { targetFieldName = value; OnPropertyChanged("TargetFieldName"); }
        }

        public bool UseFirstIfMulti
        {
            get { return useFirstIfMulti; }
            set { useFirstIfMulti = value; OnPropertyChanged("UseFirstIfMulti"); }
        }

        public string WebUrl
        {
            get
            {
                if (string.IsNullOrEmpty(webUrl))
                {
                    webUrl = ConfigManager.TryGetDefaultExternalWebUrl();
                }
                return webUrl;
            }
            set
            {
                webUrl = value;
                ConfigManager.SaveDefaultExternalWebUrl(webUrl);
                OnPropertyChanged("WebUrl");
            }
        }

        #endregion Properties

        #region Methods

        public void FieldsReceived(List<Field> availableListFields, string errorMessage)
        {
            Deployment.Current.Dispatcher.BeginInvoke(delegate()
            {
                SetRetreivalStatus(false);
                if (availableListFields != null)
                {
                    this.SourceListFields = availableListFields;
                }
                else
                {
                    if (!string.IsNullOrEmpty(errorMessage))
                    {
                        MessageBox.Show(errorMessage);
                    }
                }
            });
        }

        public void GetExternalListFields()
        {
            SetRetreivalStatus(true);
            ExternalListLookupWorker worker = new ExternalListLookupWorker();
            worker.GetFields(webUrl, listName, FieldsReceived);
        }

        public void ReadTransformValues(CSVParser.FieldTransformation transform)
        {
            if (transform != null && transform.TransformationType == CSVParser.TransformationType.ExternalLookupReplace && !string.IsNullOrEmpty(transform.TransformRule))
            {
                string rule = transform.TransformRule;
                if (!string.IsNullOrWhiteSpace(rule))
                {
                    this.WebUrl = ExternalLookupTranformParser.GetUrlFromTranformRule(rule);
                    this.ListName = ExternalLookupTranformParser.GetListNameFromTransformRule(rule);
                    this.UseFirstIfMulti = ExternalLookupTranformParser.GetMultiSettingsFromRule(rule);
                    this.BlankIfNull = ExternalLookupTranformParser.GetNullSettingsFromRule(rule);
                    this.TargetFieldName = ExternalLookupTranformParser.GetTargetFieldFromRule(rule);
                    if (!string.IsNullOrEmpty(this.webUrl) && !string.IsNullOrEmpty(this.listName) && this.SourceListFields == null)
                    {
                        GetExternalListFields();
                    }
                }
                if (!string.IsNullOrEmpty(transform.TransformValue))
                {
                    string value = transform.TransformValue;
                    int nFilters = ExternalLookupTranformParser.GetNumberOfFiltersFromValue(value);
                    if (nFilters > 0)
                    {
                        this.FieldName1 = ExternalLookupTranformParser.GetFieldName1FromValue(value);
                        this.CsvColumn1 = ExternalLookupTranformParser.GetCsvColumn1FromValue(value);
                        if (nFilters > 1)
                        {
                            this.FieldName2 = ExternalLookupTranformParser.GetFieldName2FromValue(value);
                            this.CsvColumn2 = ExternalLookupTranformParser.GetCsvColumn2FromValue(value);
                            if (nFilters > 2)
                            {
                                this.FieldName3 = ExternalLookupTranformParser.GetFieldName3FromValues(value);
                                this.CsvColumn3 = ExternalLookupTranformParser.GetCsvColumn3FromValue(value);
                            }
                        }
                    }
                }

            }
        }

        internal void OnPropertyChanged(string propertyname)
        {
            if (propertychanged != null)
            {
                this.propertychanged(this, new PropertyChangedEventArgs(propertyname));
            }
        }

        private void SetRetreivalStatus(bool retreiving)
        {
            if (retreiving)
            {
                this.FieldRetreivalStatus = "Retrieving Fields";
            }
            else
            {
                this.FieldRetreivalStatus = "Get Fields";
            }
        }

        #endregion Methods

        #region Nested Types

        public static class ExternalLookupTranformParser
        {
            #region Methods

            public static string GetCsvColumn1FromValue(string value)
            {
                string rvalue = "";
                if (!string.IsNullOrEmpty(value) && value.Contains(":"))
                {
                    if (value.Contains("|"))
                    {
                        string pair = value.Split('|')[0];
                        if (!string.IsNullOrEmpty(pair))
                        {
                            rvalue = pair.Split(':')[1];
                        }
                    }
                    else
                    {
                        //there is only one
                        rvalue = value.Split(':')[1];
                    }
                }
                return rvalue;
            }

            public static string GetCsvColumn2FromValue(string value)
            {
                string rvalue = "";
                if (!string.IsNullOrEmpty(value))
                {
                    if (value.Contains("|"))
                    {
                        string pair = value.Split('|')[1];
                        if (!string.IsNullOrEmpty(pair))
                        {
                            rvalue = pair.Split(':')[1];
                        }
                    }
                }
                return rvalue;
            }

            public static string GetCsvColumn3FromValue(string value)
            {
                string rvalue = "";
                if (!string.IsNullOrEmpty(value))
                {
                    if (value.Contains("|"))
                    {
                        string pair = value.Split('|')[2];
                        if (!string.IsNullOrEmpty(pair))
                        {
                            rvalue = pair.Split(':')[1];
                        }
                    }
                }
                return rvalue;
            }

            public static string GetFieldName1FromValue(string value)
            {
                string rvalue = "";
                if (!string.IsNullOrEmpty(value) && value.Contains(":"))
                {
                    if (value.Contains("|"))
                    {
                        string pair = value.Split('|')[0];
                        if (!string.IsNullOrEmpty(pair))
                        {
                            rvalue = pair.Split(':')[0];
                        }
                    }
                    else
                    {
                        //there is only one
                        rvalue = value.Split(':')[0];
                    }
                }
                return rvalue;
            }

            public static string GetFieldName2FromValue(string value)
            {
                string rvalue = "";
                if (!string.IsNullOrEmpty(value))
                {
                    if (value.Contains("|"))
                    {
                        string pair = value.Split('|')[1];
                        if (!string.IsNullOrEmpty(pair))
                        {
                            rvalue = pair.Split(':')[0];
                        }
                    }
                }
                return rvalue;
            }

            public static string GetFieldName3FromValues(string value)
            {
                string rvalue = "";
                if (!string.IsNullOrEmpty(value))
                {
                    if (value.Contains("|"))
                    {
                        string pair = value.Split('|')[2];
                        if (!string.IsNullOrEmpty(pair))
                        {
                            rvalue = pair.Split(':')[0];
                        }
                    }
                }
                return rvalue;
            }

            public static bool GetMultiSettingsFromRule(string rule)
            {
                bool getFirst = true;
                if (!string.IsNullOrWhiteSpace(rule))
                {
                    string[] parts = rule.Split('|');
                    if (parts.Length > 1)
                    {
                        string multisetting = parts[2];
                        bool.TryParse(multisetting, out getFirst);
                    }
                }
                return getFirst;
            }

            public static bool GetNullSettingsFromRule(string rule)
            {
                bool getBlank = false;
                if (!string.IsNullOrWhiteSpace(rule))
                {
                    string[] parts = rule.Split('|');
                    if (parts.Length > 1)
                    {
                        string nullSetting = parts[3];
                        bool.TryParse(nullSetting, out getBlank);
                    }
                }
                return getBlank;
            }

            public static int GetNumberOfFiltersFromValue(string value)
            {
                int rvalue = 0;
                if (!string.IsNullOrEmpty(value))
                {
                    string[] parts = value.Split('|');
                    rvalue = parts.Length;
                }
                return rvalue;
            }

            public static string GetTargetFieldFromRule(string rule)
            {
                string rvalue = "";
                if (!string.IsNullOrWhiteSpace(rule))
                {
                    string[] parts = rule.Split('|');
                    if (parts.Length > 1)
                    {
                        rvalue = parts[4];
                    }
                }
                return rvalue;
            }

            public static CSVParser.FieldTransformation GetTransformValue(ExternalLookupVM vm)
            {
                CSVParser.FieldTransformation rvalue = null;
                if (!string.IsNullOrEmpty(vm.fieldName1) && !string.IsNullOrEmpty(vm.webUrl) && !string.IsNullOrEmpty(vm.listName) && !string.IsNullOrEmpty(vm.targetFieldName))
                {
                    rvalue = new CSVParser.FieldTransformation();
                    rvalue.TransformationType = CSVParser.TransformationType.ExternalLookupReplace;
                    rvalue.TransformRule = vm.WebUrl + "|" + vm.ListName + "|" + vm.useFirstIfMulti.ToString() + "|" + vm.blankIfNull.ToString() + "|" + vm.targetFieldName;
                    rvalue.TransformValue = vm.fieldName1 + ":" + vm.csvColumn1;
                    if (!string.IsNullOrEmpty(vm.fieldName2))
                    {
                        rvalue.TransformValue = rvalue.TransformValue + "|" + vm.fieldName2 + ":" + vm.csvColumn2;
                    }
                    if (!string.IsNullOrEmpty(vm.fieldName3))
                    {
                        rvalue.TransformValue = rvalue.TransformValue + "|" + vm.fieldName3 + ":" + vm.csvColumn3;
                    }

                }
                return rvalue;
            }

            public static string GetUrlFromTranformRule(string rule)
            {
                string rvalue = "";
                if (!string.IsNullOrWhiteSpace(rule))
                {
                    string[] parts = rule.Split('|');
                    if (parts.Length > 1)
                    {
                        rvalue = parts[0];
                    }
                }
                return rvalue;
            }

            internal static string GetListNameFromTransformRule(string rule)
            {
                string rvalue = "";
                if (!string.IsNullOrWhiteSpace(rule))
                {
                    string[] parts = rule.Split('|');
                    if (parts.Length > 1)
                    {
                        rvalue = parts[1];
                    }
                }
                return rvalue;
            }

            #endregion Methods
        }

        #endregion Nested Types
    }
}